﻿using System;
using System.Reflection;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Windows.Forms;

namespace RuleCode.Common
{
    public class SessionFactory
    {
        private static SessionFactory instance;


        #region 构造函数
        public SessionFactory()
        {
            this.fieldTableList = new List<TableField>();
            this.tableList = new List<Table>();


            //获取Table类所在的程序集中所有的派生类CustomerTable,OrderTable...
            //这一段代码很重要
            Assembly assembly = typeof(Table).Assembly;
            System.Type[] typesInTableAssembly = assembly.GetTypes();
            this.virtualTables = new List<System.Type>();
            foreach (System.Type type in typesInTableAssembly)
            {
                if (type.BaseType == typeof(Table))           //或者 type.IsSubclassOf(typeof(Table))，效果一样
                    //if (type.IsSubclassOf(typeof(Table)))
                    this.VirtualTables.Add(type);
            }

            assembly = RuleCode.Common.AssemblyClass.MyAssembly;
            System.Type[] types = assembly.GetTypes();
            foreach (System.Type type in types)
            {
                if (type.BaseType == typeof(Table))
                    this.VirtualTables.Add(type);
            }

            //根据VirtualTables 来得到VirtualRelations
            List<string> keyNames = new List<string>();
            string relationName;
            this.virtualRelations = new List<VirtualRelation>();
            foreach (System.Type parentTableType in this.VirtualTables)
            {
                foreach (System.Type childTableType in this.VirtualTables)
                {
                    if (parentTableType != childTableType)
                    {
                        keyNames = GetVirtualConstraint(parentTableType, childTableType);
                        if (keyNames != null)
                        {
                            object[] parentAttributes = parentTableType.GetProperty("Name").GetCustomAttributes(typeof(DefaultValueAttribute), true);
                            object[] childAttributes = childTableType.GetProperty("Name").GetCustomAttributes(typeof(DefaultValueAttribute), true);
                            relationName = ((DefaultValueAttribute)parentAttributes[0]).Value.ToString() + ((DefaultValueAttribute)childAttributes[0]).Value.ToString();
                            this.VirtualRelations.Add(new VirtualRelation(relationName, keyNames.ToArray(), parentTableType, childTableType));
                        }
                    }
                }
            }
        }
        #endregion

        #region 对自身的静态调用
        /// <summary>
        /// 对自身的静态调用
        /// </summary>
        public static SessionFactory Instance
        {
            get
            {
                if (instance == null)
                    instance = new SessionFactory();
                return instance;
            }
        }
        #endregion


        #region  虚拟表集合VirtualTables 和虚拟关系映射VirtualRelations
        //在构造函数里面初始化
        private List<VirtualRelation> virtualRelations;
        //在构造函数里面初始化
        private List<System.Type> virtualTables;

        /// <summary>
        /// 获取所有的表结构，即：从Table类派生出来的CustomerTable,OrderTable...等等
        /// </summary>
        public List<System.Type> VirtualTables
        { get { return this.virtualTables; } }

        /// <summary>
        /// 获取所有表结构之间可能存在的表关系的虚拟映射
        /// </summary>
        public List<VirtualRelation> VirtualRelations
        { get { return this.virtualRelations; } }

        public System.Type GetTableTypeByName(string tableName)
        {
            Assembly assembly = RuleCode.Common.AssemblyClass.MyAssembly;
            System.Type[] types = assembly.GetTypes();
            foreach (System.Type type in types)
            {
                if (type.Name == tableName)
                    return type;
            }
            return null;
            /*
            foreach (System.Type tableType in this.VirtualTables)
            {
                PropertyInfo pInfo = tableType.GetProperty("Name");
                object[] attributes = pInfo.GetCustomAttributes(typeof(DefaultValueAttribute), true);
                if (((DefaultValueAttribute)attributes[0]).Value.ToString () == tableName)
                    return tableType;
            }
             * */

        }

        /// <summary>
        /// 根据Table类型和KeyCateggory获得Table类型的虚拟关系集合
        /// 当参数keyCate为KeyCategory.FOREIGNKEY,则返回以Table类型表为子表的关系集合；
        /// 当参数keyCate为KeyCategory.PRIMARYKEY,则返回以Table类型表为父表的关系集合；
        /// </summary>
        /// <param name="tableType"></param>
        /// <param name="keyCate"></param>
        /// <returns></returns>
        public List<VirtualRelation> GetVirtualRelations(System.Type tableType, KeyCategory keyCate)
        {
            List<VirtualRelation> virtualRelation = new List<VirtualRelation>();
            if (!tableType.IsSubclassOf(typeof(Table)))
                return null;
            foreach (VirtualRelation vRelation in this.VirtualRelations)
            {
                switch (keyCate)
                {
                    case KeyCategory.FOREIGNKEY:                     //返回以Table类型表为子表的关系集合
                        {
                            if (vRelation.ChildTableType == tableType)
                                virtualRelation.Add(vRelation);
                            break;
                        }
                    case KeyCategory.PRIMARYKEY:                     //返回以Table类型表为父表的关系集合
                        {
                            if (vRelation.ParentTableType == tableType)
                                virtualRelation.Add(vRelation);
                            break;
                        }
                    default:
                        { break; }
                }
            }
            return virtualRelation;
        }

        /// <summary>
        /// GetKeyNames()，根据Table派生类CustomerTable , OrderTable得到主键或者外键列名集合
        /// </summary>
        /// <param name="tabletype"></param>
        /// <param name="keyCate"></param>
        /// <returns></returns>
        public List<string> GetKeyNames(System.Type tabletype, KeyCategory keyCate)
        {
            List<string> KeyNames = new List<string>();
            if (tabletype.IsSubclassOf(typeof(Table)))
            {
                PropertyInfo[] properties = tabletype.GetProperties();
                foreach (PropertyInfo pInfo in properties)
                {
                    //只有一个元素FieldAttribute
                    object[] attributes = pInfo.GetCustomAttributes(typeof(FieldAttribute), true);
                    if (attributes.Length != 0)
                    {
                        switch (keyCate)
                        {
                            case KeyCategory.FOREIGNKEY:
                                {
                                    if (((FieldAttribute)attributes[0]).FieldCate == FieldCategory.FOREIGNKEY)
                                        KeyNames.Add(pInfo.Name);
                                    break;
                                }
                            case KeyCategory.PRIMARYKEY:
                                {
                                    if (((FieldAttribute)attributes[0]).FieldCate == FieldCategory.PRIMARYKEY)
                                        KeyNames.Add(pInfo.Name);
                                    break;
                                }
                            default:
                                { break; }
                        }
                    }
                }
            }
            else
            {
                MessageBox.Show("您给定的参数类型不是Table类型的派生类！");
            }
            return KeyNames;
        }


        /// <summary>
        /// 验证两个Table类的派生类是否可能存在父子关系
        /// </summary>
        /// <param name="parentTableType"></param>
        /// <param name="childTableType"></param>
        /// <returns></returns>
        public List<string> GetVirtualConstraint(System.Type parentTableType, System.Type childTableType)
        {
            List<string> parentKeys = new List<string>();
            List<string> childKeys = new List<string>();
            if (parentTableType.IsSubclassOf(typeof(Table)) && childTableType.IsSubclassOf(typeof(Table)))
            {
                parentKeys = GetKeyNames(parentTableType, KeyCategory.PRIMARYKEY);
                childKeys = GetKeyNames(childTableType, KeyCategory.FOREIGNKEY);
                if (parentKeys.Count > 0 && childKeys.Count > 0)
                {
                    //如果子表的外键列名集合包括主表所有的主键列名集合，则两个表之间存在父子关系
                    foreach (string key in parentKeys)
                        if (!childKeys.Contains(key))
                            return null;
                    return parentKeys;
                }
                return null;
            }
            //如果两个参数不是Table类型的派生类
            else
            {
                MessageBox.Show("您给定的参数类型不是Table类型的派生类！");
                return null;
            }

        }
        #endregion



        #region 所有Table对象的存储，以便每个Table有自己的Index,List<table>;
        private List<Table> tableList;

        public List<Table> TableList
        { get { return this.tableList; } }

        /// <summary>
        /// 根据Table类型得到Table对象
        /// </summary>
        /// <param name="tableType"></param>
        /// <returns></returns>
        public Table GetTable(System.Type tableType)
        {
            if (tableType.IsSubclassOf(typeof(Table)))
            {
                foreach (Table table in this.TableList)
                    if (table.GetType() == tableType)
                        return table;
            }
            return null;
        }
        #endregion


        #region 根据Table类型和Field类型获得Table对象中的Field 字段的值
        public TableFieldType GetFieldValue() { return null; }
        #endregion

        #region  所有Table中的字段Field的存储，List<Dictionary<table,field>> 必须预先存储，还没有写好存储代码
        private List<TableField> fieldTableList;
        public List<TableField> FieldTableList
        { get { return this.fieldTableList; } }
        public TableFieldType GetField()
        { return null; }


        public static bool FieldExistInTable(System.Type tableType, System.Type TableFieldType)
        {
            if (!tableType.IsSubclassOf(typeof(Table)))
                return false;
            PropertyInfo[] properties = tableType.GetProperties();
            foreach (PropertyInfo pInfo in properties)
            {
                object[] objects = pInfo.GetCustomAttributes(typeof(FieldAttribute), true);
                if (((FieldAttribute)objects[0]).FieldCate == FieldCategory.FOREIGNKEY || ((FieldAttribute)objects[0]).FieldCate == FieldCategory.NORMAL
                    || ((FieldAttribute)objects[0]).FieldCate == FieldCategory.PRIMARYKEY)
                    return true;
            }
            return false;
        }
        #endregion

        //public object GetField

        /*
        #region 增加属性的方法AddTableIndex(),AddFieldGroup(),AddDeleteAction()等等
        public bool AddTableIndex(TableIndex tableIndex)
        {
            this.TableIndexList.Add(tableIndex);
            return true;

            string createIndexCommandString = SqlLanguage.CREATE;
            string indexCategory;
            switch (tableIndex.IndexCategory)
            {
                case TableIndexCategory.CLUSTERED:
                    {
                        indexCategory = SqlLanguage.CLUSTERED;
                        break;
                    }
                case TableIndexCategory.NONCLUSTERED:
                    {
                        indexCategory = SqlLanguage.NONCLUSTERED;
                        break;
                    }
                case TableIndexCategory.UNIQUE:
                    {
                        indexCategory = SqlLanguage.UNIQUE;
                        break;
                    }
                default:
                    break;
            }
            createIndexCommandString += indexCategory;
            createIndexCommandString += SqlLanguage.INDEX + tableIndex.Name + SqlLanguage.SPACE + SqlLanguage.ON;
            //createIndexCommandString +=tableIndex .TableType


        }

        #endregion
        */

    }

    /// <summary>
    /// TableField 结构 用来存储Table和Field的匹配对
    /// </summary>
    public struct TableField
    {
        public Table table;
        public TableFieldType fieldInTable;

        public TableField(Table _table, TableFieldType _field)
        {
            this.table = _table;
            this.fieldInTable = _field;
        }
    }

    /// <summary>
    /// RelationTables 结构
    /// </summary>
    public struct RelationTables
    {
        public Table parentTable;
        public Table childTable;

        public RelationTables(Table pTable, Table cTable)
        {
            this.parentTable = pTable;
            this.childTable = cTable;
        }
    }

   

    ///// <summary>
    ///// 结构体 DeleteAction 存在于父表中，其中有子表类型RelateTableType和DeleteActionEnum
    ///// </summary>
    //public struct DeleteAction
    //{
    //    public DELETEACTION deleteActionEnum;
    //    public System.Type relateTableType;

    //    public DeleteAction(DELETEACTION dAction, System.Type tableType)
    //    {
    //        this.deleteActionEnum = dAction;
    //        this.relateTableType = tableType;
    //    }

    //    /// <summary>
    //    /// 获取或设置表之间的Delete()操作的级联关系
    //    /// </summary>
    //    public DELETEACTION DeleteActionEnum
    //    {
    //        get { return this.deleteActionEnum; }
    //        set { this.deleteActionEnum = value; }
    //    }

    //    /// <summary>
    //    /// 获取表的子表的类型
    //    /// </summary>
    //    public System.Type RelateTableType
    //    { get { return this.relateTableType; } }



    //}




}
